#include <iostream>
#include <regex>
#include <string>
#include <vector>

void SplitString(const std::string &s, std::vector<std::string> &tokens, const std::string &delimiters = ",")
{
    std::string::size_type lastPos = s.find_first_not_of(delimiters, 0);
    std::string::size_type pos = s.find_first_of(delimiters, lastPos);
    while (std::string::npos != pos || std::string::npos != lastPos)
    {
        tokens.push_back(s.substr(lastPos, pos - lastPos));
        //tokens.emplace_back(s.substr(lastPos, pos - lastPos));
        lastPos = s.find_first_not_of(delimiters, pos);
        pos = s.find_first_of(delimiters, lastPos);
    }
}

void SplitString1(const std::string &s, std::vector<std::string> &tokens, const char delimiter = ',')
{
    //std::regex r(delimiters);必须单独定义一个变量，否则编译错误：
    //错误 C2280“std::regex_token_iterator<std::_String_const_iterator<std::_String_val<std::_Simple_types<char>>>, char, std::regex_traits<char>>::regex_token_iterator(_BidIt, _BidIt, const std::basic_regex<char, std::regex_traits<char>> &&, int, std::regex_constants::match_flag_type)”: 尝试引用已删除的函数
    //tokens = std::vector<std::string>(std::sregex_token_iterator(s.begin(), s.end(), std::regex(delimiter), -1), std::sregex_token_iterator());
	//std::regex r(std::string(delimiter, 1));
	std::string d(1, delimiter);
	std::regex r(d);
	tokens = std::vector<std::string>(std::sregex_token_iterator(s.begin(), s.end(), r, -1), std::sregex_token_iterator());
}

void SplitString1(const std::string &s, std::vector<std::string> &tokens, const std::string &delimiters = ",", bool bDelimitersAsWhole = false, bool bKeepEmptyParts = true)
{
	//std::regex r(delimiters);必须单独定义一个变量，否则编译错误：
	//错误 C2280“std::regex_token_iterator<std::_String_const_iterator<std::_String_val<std::_Simple_types<char>>>, char, std::regex_traits<char>>::regex_token_iterator(_BidIt, _BidIt, const std::basic_regex<char, std::regex_traits<char>> &&, int, std::regex_constants::match_flag_type)”: 尝试引用已删除的函数
	//tokens = std::vector<std::string>(std::sregex_token_iterator(s.begin(), s.end(), std::regex(delimiters), -1), std::sregex_token_iterator());
	std::regex r;
	if (delimiters.size() > 1 && !bDelimitersAsWhole)
	{
		std::string a = "[";
		a += delimiters[0];
		for (int i = 1; i < delimiters.size(); i++)
		{
			a += '|';
			a += delimiters[i];
		}
		a += "]";
		r.assign(a);
	}
	else
	{
		r.assign(delimiters);
	}

	if (bKeepEmptyParts)
	{
		tokens = std::vector<std::string>(std::sregex_token_iterator(s.begin(), s.end(), r, -1), std::sregex_token_iterator());
	}
	else
	{
		std::vector<std::string> vs(std::sregex_token_iterator(s.begin(), s.end(), r, -1), std::sregex_token_iterator());
		tokens.clear();
		for (const auto v : vs)
		{
			if (v.size())
			{
				tokens.push_back(v);
			}
		}
	}
}

typedef std::vector<std::string> StringList;
void SplitString2(const std::string &src, StringList &list, const char delimiter)
{
    std::string::size_type start = src.find_first_not_of(delimiter);
    while (start != std::string::npos)
    {
        std::string::size_type end = src.find_first_of(delimiter, start);
        if (end != std::string::npos)
        {
            list.push_back(std::string(src, start, end-start));
            start = src.find_first_not_of(delimiter, end);
        }
        else
        {
            list.push_back(std::string(src, start, src.size()-start));
            start = end;
        }
    }
}

void SplitString2(const std::string &src, StringList &list, const std::string &delimiter = ",")
{
    std::string::size_type start = src.find_first_not_of(delimiter);
    while (start != std::string::npos)
    {
        std::string::size_type end = src.find_first_of(delimiter, start);
        if (end != std::string::npos)
        {
            list.push_back(std::string(src, start, end-start));
            start = src.find_first_not_of(delimiter, end);
        }
        else
        {
            list.push_back(std::string(src, start, src.size()-start));
            start = end;
        }
    }
}

int main(int argc, char **argv)
{
    std::vector<std::string> ss = { "1,2,3,4,5,6", "1,2,3,,4,5,6", "1 2 3 4 5 6", "1 2 3  4 5 6", "1,2,3,4 5 6", "1,2,3, 4 5 6" };
	std::vector<std::string> seps = { ",", " ", ", " };
	for (const auto &sep : seps)
	{
		for (const auto &s : ss)
		{
			std::vector<std::string> tokens;
			SplitString(s, tokens, sep);
			std::cout << "sep:\"" << sep << "\"\tsrc:\"" << s << "\"\n";
			std::cout << "SplitString00," << tokens.size() << ":";
			for (auto t : tokens)
			{
				std::cout << t << "-";
			}
			std::cout << std::endl;

			SplitString1(s, tokens, sep);
			std::cout << "SplitString10," << tokens.size() << ":";
			for (auto t : tokens)
			{
				std::cout << t << "-";
			}
			std::cout << std::endl;

			SplitString1(s, tokens, sep, false, false);
			std::cout << "SplitString11," << tokens.size() << ":";
			for (auto t : tokens)
			{
				std::cout << t << "-";
			}
			std::cout << std::endl;

			tokens.clear();
			SplitString2(s, tokens, sep[0]);
			std::cout << "SplitString20," << tokens.size() << ":";
			for (auto t : tokens)
			{
				std::cout << t << "-";
			}
			std::cout << std::endl;

			tokens.clear();
			SplitString2(s, tokens, sep);
			std::cout << "SplitString21," << tokens.size() << ":";
			for (auto t : tokens)
			{
				std::cout << t << "-";
			}
			std::cout << std::endl;
		}
	}
	getchar();
	return 0;
}

//sep:"," src:"1,2,3,4,5,6"
//SplitString00,6:1-2-3-4-5-6-
//SplitString10,6:1-2-3-4-5-6-
//SplitString11,6:1-2-3-4-5-6-
//SplitString20,6:1-2-3-4-5-6-
//SplitString21,6:1-2-3-4-5-6-
//sep:"," src:"1,2,3,,4,5,6"
//SplitString00,6:1-2-3-4-5-6-
//SplitString10,7:1-2-3--4-5-6-
//SplitString11,6:1-2-3-4-5-6-
//SplitString20,6:1-2-3-4-5-6-
//SplitString21,6:1-2-3-4-5-6-
//sep:"," src:"1 2 3 4 5 6"
//SplitString00,1:1 2 3 4 5 6-
//SplitString10,1:1 2 3 4 5 6-
//SplitString11,1:1 2 3 4 5 6-
//SplitString20,1:1 2 3 4 5 6-
//SplitString21,1:1 2 3 4 5 6-
//sep:"," src:"1 2 3  4 5 6"
//SplitString00,1:1 2 3  4 5 6-
//SplitString10,1:1 2 3  4 5 6-
//SplitString11,1:1 2 3  4 5 6-
//SplitString20,1:1 2 3  4 5 6-
//SplitString21,1:1 2 3  4 5 6-
//sep:"," src:"1,2,3,4 5 6"
//SplitString00,4:1-2-3-4 5 6-
//SplitString10,4:1-2-3-4 5 6-
//SplitString11,4:1-2-3-4 5 6-
//SplitString20,4:1-2-3-4 5 6-
//SplitString21,4:1-2-3-4 5 6-
//sep:"," src:"1,2,3, 4 5 6"
//SplitString00,4:1-2-3- 4 5 6-
//SplitString10,4:1-2-3- 4 5 6-
//SplitString11,4:1-2-3- 4 5 6-
//SplitString20,4:1-2-3- 4 5 6-
//SplitString21,4:1-2-3- 4 5 6-
//sep:" " src:"1,2,3,4,5,6"
//SplitString00,1:1,2,3,4,5,6-
//SplitString10,1:1,2,3,4,5,6-
//SplitString11,1:1,2,3,4,5,6-
//SplitString20,1:1,2,3,4,5,6-
//SplitString21,1:1,2,3,4,5,6-
//sep:" " src:"1,2,3,,4,5,6"
//SplitString00,1:1,2,3,,4,5,6-
//SplitString10,1:1,2,3,,4,5,6-
//SplitString11,1:1,2,3,,4,5,6-
//SplitString20,1:1,2,3,,4,5,6-
//SplitString21,1:1,2,3,,4,5,6-
//sep:" " src:"1 2 3 4 5 6"
//SplitString00,6:1-2-3-4-5-6-
//SplitString10,6:1-2-3-4-5-6-
//SplitString11,6:1-2-3-4-5-6-
//SplitString20,6:1-2-3-4-5-6-
//SplitString21,6:1-2-3-4-5-6-
//sep:" " src:"1 2 3  4 5 6"
//SplitString00,6:1-2-3-4-5-6-
//SplitString10,7:1-2-3--4-5-6-
//SplitString11,6:1-2-3-4-5-6-
//SplitString20,6:1-2-3-4-5-6-
//SplitString21,6:1-2-3-4-5-6-
//sep:" " src:"1,2,3,4 5 6"
//SplitString00,3:1,2,3,4-5-6-
//SplitString10,3:1,2,3,4-5-6-
//SplitString11,3:1,2,3,4-5-6-
//SplitString20,3:1,2,3,4-5-6-
//SplitString21,3:1,2,3,4-5-6-
//sep:" " src:"1,2,3, 4 5 6"
//SplitString00,4:1,2,3,-4-5-6-
//SplitString10,4:1,2,3,-4-5-6-
//SplitString11,4:1,2,3,-4-5-6-
//SplitString20,4:1,2,3,-4-5-6-
//SplitString21,4:1,2,3,-4-5-6-
//sep:", "        src:"1,2,3,4,5,6"
//SplitString00,6:1-2-3-4-5-6-
//SplitString10,6:1-2-3-4-5-6-
//SplitString11,6:1-2-3-4-5-6-
//SplitString20,6:1-2-3-4-5-6-
//SplitString21,6:1-2-3-4-5-6-
//sep:", "        src:"1,2,3,,4,5,6"
//SplitString00,6:1-2-3-4-5-6-
//SplitString10,7:1-2-3--4-5-6-
//SplitString11,6:1-2-3-4-5-6-
//SplitString20,6:1-2-3-4-5-6-
//SplitString21,6:1-2-3-4-5-6-
//sep:", "        src:"1 2 3 4 5 6"
//SplitString00,6:1-2-3-4-5-6-
//SplitString10,6:1-2-3-4-5-6-
//SplitString11,6:1-2-3-4-5-6-
//SplitString20,1:1 2 3 4 5 6-
//SplitString21,6:1-2-3-4-5-6-
//sep:", "        src:"1 2 3  4 5 6"
//SplitString00,6:1-2-3-4-5-6-
//SplitString10,7:1-2-3--4-5-6-
//SplitString11,6:1-2-3-4-5-6-
//SplitString20,1:1 2 3  4 5 6-
//SplitString21,6:1-2-3-4-5-6-
//sep:", "        src:"1,2,3,4 5 6"
//SplitString00,6:1-2-3-4-5-6-
//SplitString10,6:1-2-3-4-5-6-
//SplitString11,6:1-2-3-4-5-6-
//SplitString20,4:1-2-3-4 5 6-
//SplitString21,6:1-2-3-4-5-6-
//sep:", "        src:"1,2,3, 4 5 6"
//SplitString00,6:1-2-3-4-5-6-
//SplitString10,7:1-2-3--4-5-6-
//SplitString11,6:1-2-3-4-5-6-
//SplitString20,4:1-2-3- 4 5 6-
//SplitString21,6:1-2-3-4-5-6-